﻿using System;
using System.Globalization;
using System.Linq;
using System.Speech.Recognition;

using EnvDTE80;

namespace ThirdHand
{
    /// <summary>
    /// Listens for commands and processes them when recognized.
    /// </summary>
    public sealed class ThirdHandSpeechListener : IDisposable
    {
        private DTE2 theApplication;
        private ThirdHandCommandBindingList _commands;
        private SpeechRecognizer _recognizer;
        private Grammar _grammar;

        /// <summary>
        /// Main constructor
        /// </summary>
        /// <param name="application">VS Instance</param>
        public ThirdHandSpeechListener(DTE2 application)
        {
            theApplication = application;
        }

        /// <summary>
        /// Loads the commands from storage.
        /// </summary>
        public void Load()
        {
            _commands = ThirdHandCommandBindingList.LoadFromStorage();
        }

        void GrammarSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            foreach (ThirdHandCommand thc in
                _commands.Where(thc => string.Compare(thc.SpokenWord, e.Result.Text, true, CultureInfo.CurrentCulture) == 0))
            {
                try
                {
                    theApplication.ExecuteCommand(thc.Command, string.Empty);
                }
                catch (Exception ex)
                {
                    theApplication.StatusBar.Text = ex.Message;
                }
            }
        }

        /// <summary>
        /// Loads the commands into a grammar, and starts up the recognizer.
        /// </summary>
        public void Listen()
        {
            Choices ch = new Choices(_commands.Select(thc => thc.SpokenWord).ToArray());

            GrammarBuilder gb = new GrammarBuilder();
            gb.Append(ch);
            _grammar = new Grammar(gb);
            _grammar.SpeechRecognized += GrammarSpeechRecognized;
            
            _recognizer = new SpeechRecognizer();
            _recognizer.LoadGrammar(_grammar);

            _recognizer.Enabled = true;
            _recognizer.PauseRecognizerOnRecognition = true;

        }

        /// <summary>
        /// Unloads the grammar from the recognition engine.
        /// </summary>
        public void Ignore()
        {
            if (_grammar != null)
            {
                _recognizer.UnloadGrammar(_grammar);
            }
        }

        /// <summary>
        /// Shuts down the recognizer.
        /// </summary>
        public void Unload()
        {
            _recognizer.UnloadGrammar(_grammar);
            _recognizer.Dispose();

        }

        #region IDisposable Members

        /// <summary>
        /// Dispose the recognizer if it is still around.
        /// </summary>
        public void Dispose()
        {
            if (_recognizer != null)
            {
                _recognizer.Dispose();
            }
        }

        #endregion
    }
}
